use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
use axum::{http, middleware, routing::{get, post}, Extension, Router, ServiceExt};
use axum::extract::State;
use axum::http::{HeaderValue, Method};
use meilisearch_sdk::client::Client;
use minio_rsc::Minio;
use minio_rsc::provider::StaticProvider;
use redis::aio::MultiplexedConnection;
use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use tower_http::cors::{AllowHeaders, AllowOrigin, Any, CorsLayer};
use tracing::{info, log, Level};
use tracing_subscriber::{EnvFilter, FmtSubscriber};
use crate::config::AppConfig;
use crate::graphql::{create_schema, graphql_handler, graphql_playground};
use crate::handler::login_handler::{login_handle, logout_handle, refresh_token_handle, register_handle};
use crate::scheduler::TaskScheduler;


pub async fn run() -> std::io::Result<()>  {
    
    let cfg = AppConfig::load().unwrap();

    // 设置日志记录器
    let subscriber = FmtSubscriber::builder()
        // 直接在代码中指定日志过滤规则，而不是使用环境变量
        .with_env_filter(
            EnvFilter::try_new(
                "lab_monolith_rust=info,\
                axum=debug,\
                axum::rejection=trace,\
                tower_http=trace"
            )
                .unwrap_or_else(|_| EnvFilter::new("info")) // 备用方案
        )
        .finish();
    tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");


    // 初始化数据库连接池
    // let mut opt = ConnectOptions::new("mysql://root:982469065@localhost:3306/lab");
    let mut opt = ConnectOptions::new(cfg.mysql.url);
    opt.max_connections(100)
        .min_connections(5)
        .connect_timeout(Duration::from_secs(8))
        .acquire_timeout(Duration::from_secs(8))
        .idle_timeout(Duration::from_secs(8))
        .max_lifetime(Duration::from_secs(8))
        .sqlx_logging(false)
        .sqlx_logging_level(log::LevelFilter::Info);
    let db = Database::connect(opt).await.expect("Failed to get mysql connection");

    // redis 客户端
    let client = redis::Client::open(cfg.redis.url)

        .expect("Failed to create Redis client");
    let conn = client.get_multiplexed_async_connection()
        .await
        .expect("Failed to get Redis connection");



    // 初始化客户端
    let meilisearch_client = Client::new(&cfg.meilisearch.url, cfg.meilisearch.api_key).unwrap();



    // 启动任务调度器
    let scheduler = TaskScheduler::new(db.clone(), conn.clone());
    tokio::spawn(async move {
        if let Err(e) = scheduler.poll_and_execute_tasks().await {
            eprintln!("任务调度器出错: {}", e);
        }
    });

    // minio 客户端
    let provider = StaticProvider::new(cfg.minio.access_key, cfg.minio.secret_key, None);
    let minio = Minio::builder()
        .endpoint(&cfg.minio.endpoint)
        .provider(provider)
        .secure(true)
        .build()
        .expect("Failed to create Minio client");


    info!("Connecting to MinIO at: {}", cfg.minio.endpoint);

    // 注册graphql
    let app_schema = create_schema(db.clone(), conn.clone(), minio, meilisearch_client);


    // let config = RustlsConfig::from_pem_file(
    //     PathBuf::from(env!("CARGO_MANIFEST_DIR"))
    //         .join("server.crt"),
    //     PathBuf::from(env!("CARGO_MANIFEST_DIR"))
    //         .join("server_pkcs8_key.pem"),
    // )
    //     .await
    //     .unwrap();

    let cors = CorsLayer::new()
        // .allow_origin(AllowOrigin::any()) // 允许所有来源
        .allow_origin([
            "https://localhost".parse::<HeaderValue>().unwrap(),
            "https://47.116.160.210".parse::<HeaderValue>().unwrap(),
            "https://wujianming.xyz".parse::<HeaderValue>().unwrap(),
        ])
        .allow_methods(vec![Method::GET, Method::POST])
        .allow_headers(vec![
            http::header::CONTENT_TYPE,
            http::header::AUTHORIZATION,
            http::header::ACCEPT,
        ])
        .allow_credentials(true); // 允许携带凭证
        // .allow_headers(AllowHeaders::any()); // 允许所有请求头
    // 创建不需要认证的路由（登录、注册等）

    let app_state = Arc::new(AppState {
        db: db.clone(),
        redis: conn.clone(),
    });

    let app = Router::new()
        .route("/api/graphql", get(graphql_playground).post(graphql_handler))
        .route("/api/auth/login", post(login_handle))
        .route("/api/auth/logout", post(logout_handle))
        .route("/api/auth/register", post(register_handle)) 
        .route("/api/auth/refresh_token", post(refresh_token_handle)) 
        .layer(Extension(app_schema.clone()))
        .route_layer(middleware::from_fn_with_state(
            conn.clone(),
            |headers, State(redis_conn): State<MultiplexedConnection>, req, next| {
                crate::middleware::jwt_middleware::jwt_middleware(headers, redis_conn, req, next)
            }
        ))
        .layer(cors)
        .with_state(app_state); // 应用于整个 Router 的顶层


    // let mut server = axum_server::bind_rustls(SocketAddr::from(([0, 0, 0, 0], 8443)), config);
    let server = axum_server::bind(SocketAddr::from(([0, 0, 0, 0], 8000))); // 更改端口为8000或其他HTTP端口

    // server.http_builder().http2().enable_connect_protocol();

    server.serve(app.into_make_service()).await?;


    Ok(())
}

#[derive(Clone)]
pub struct AppState {
    pub db: DatabaseConnection, // 数据库连接池
    pub redis: MultiplexedConnection, // Redis 连接池
}